#include <stdio.h> 
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>

#include "key.h"
#include "sm2.h"
#include "sm3.h"
#include "sm4.h"
#include "seg7.h"
#include "led.h"
#include "common_func.h"
#include "core_time.h"

//BSP板级支持包所需全局变量
unsigned long UART_BASE = 0xbf000000;					//UART16550的虚地址
unsigned long CONFREG_TIMER_BASE = 0xbf20f100;			//CONFREG计数器的虚地址
unsigned long CONFREG_CLOCKS_PER_SEC = 50000000L;		//CONFREG时钟频率
unsigned long CORE_CLOCKS_PER_SEC = 33000000L;			//处理器核时钟频率

//value--------------------------------------------------------------
ECCrefPrivateKey prikey = {
	.K = {0x526FF0B7, 0x5DB2D940, 0x89FA76A1, 0x983DB034, 
		  0x0D79FF37, 0xACC58E21, 0x4FAE46A3, 0xC7DAE211}};
ECCrefPublicKey pubkey = {
	.x = {0x958E4164, 0x204F52F5, 0x4AE34032, 0x23EE5F42, 
		  0xE01ED9EB, 0xECBEE98B, 0x04424CCE, 0x1E7AABD4},
	.y = {0xB3891DE9, 0xBFB2F38F, 0x4F252C38, 0x0590F206, 
		  0xBDA63306, 0x626B646C, 0x76C1D7D9, 0x15D464F5}};
uint32_t random_k[8] = {
	0x16a25a3d, 0x8e495e9e, 0xfeeb31ce, 0x49e0f38e,   
	0x0d00828e, 0xf8b0c6b4, 0x2b811458, 0x03f0b21f};
char *pin = "qwer1234";
uint8_t sm4_key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 
				   0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
//value^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

ECCSignature ins_sign = {0};
uint8_t ins_enc[16]  = {0};
uint32_t ins_hash[8] = {0};
uint8_t ins_flag = 0;
uint8_t door_state = 1; 
uint8_t ins_dec[16]  = {0};
uint32_t switch_data = 0;
uint32_t attack_count = 0;
uint8_t ins_door[16] = { 
	0xAA,		//head
	0x00, 0x10,	//len 16B
	0x01,		//ver
	0x11, 0x22, 0x33, 0x44, 0x55, 0x66,	//id 48bit
	0x11,		//ins
	0x00, 0x01,	//para
	0x00, 0x00, //crc
	0x55};		//tail


//mode: 0 = negedge ,1 or else W= posedge
void exti_key_init(uint8_t key_id, uint8_t mode)
{
	if(key_id < 4)
	{
		uint32_t value_temp = 0x1;
		value_temp = value_temp << key_id;
		RegWrite(0xbf20f004, value_temp);//edge
		RegWrite(0xbf20f008, mode ? 1:0);//pol
		RegWrite(0xbf20f00c, value_temp);//clr
		RegWrite(0xbf20f000, value_temp);//en
	}
}

uint32_t ins_enc_sign(uint32_t sm2_key_id, uint32_t sm4_key_id, uint8_t *sm2_key_pin, uint8_t *sm4_key_pin, 
	uint32_t *random_k_in, uint8_t *ins_data_in, uint8_t *ins_enc_out, uint32_t *ins_hash_out, ECCSignature *ins_sign_out)
{
	uint32_t ret = 0;
	
	//enc---------------
	ret = access_key(KEY_TYPE_SM4, sm4_key_id, sm4_key_pin);
	if(ret)
	{
        printf("[ERROR] Access SM4 key faild! (Key ID: %d)\n", sm4_key_id);
	}
	//加密
	ret = sm4_init_inkey(0);
	if(ret)
	{
        printf("[ERROR] SM4 init faild in ENC mode! (Error code: 0x%04X)\n", ret);
	}
	ret = sm4_enc_dec(ins_data_in, ins_enc_out);
	if(ret)
	{
		//printf("SM4 enc faild!\n");
		return 0x260;
	}
	else
	{
        printf("[INFO] SM4 encryption completed successfully\n");
	}
	release_key(KEY_TYPE_SM4, sm4_key_id);
	
	//hash------------
	SM3_Handle_t s_handle;
	memset(&s_handle, 0x0, sizeof(SM3_Handle_t));
	uint32_t ins_data_in_u32_temp[4] = {0};
	memcpy(ins_data_in_u32_temp, ins_data_in, 16);
	ret = sm3_init(&s_handle);
	if(ret)
	{
        printf("[ERROR] SM3 init faild! (Error code: 0x%04X)\n", ret);
	}
	for(int i = 0; i < 4; i++)
	{
		ret = sm3_update(&s_handle, ins_data_in_u32_temp[i]);
		if(ret)
		{
            printf("[ERROR] SM3 update faild in round %d! (Error code: 0x%04X)\n", i, ret);
			break;
		}
	}
	ret = sm3_final(&s_handle, ins_hash_out);
	if(ret)
	{
		//printf("SM3 clear faild!\n");
		return 0x261;
	}
	else
	{
        printf("[INFO] SM3 hash generated successfully\n");
	}
	
	//sign--------
	ret = access_key(KEY_TYPE_SM2, sm2_key_id, sm2_key_pin);
	if(ret)
	{
        printf("[ERROR] Access SM2 key faild! (Key ID: %d)\n", sm2_key_id);
	}
	ret = sm2_signature_inkey(random_k_in, ins_hash_out, ins_sign_out);
	if(ret)
	{
		//printf("SM2 sign faild!\n");
		return 0x262;
	}
	else
	{
        printf("[INFO] SM2 signature generated successfully\n");
	}
	release_key(KEY_TYPE_SM2, sm2_key_id);
	
	return 0;
}

uint32_t ins_dec_veri(uint32_t sm2_key_id, uint32_t sm4_key_id, uint8_t *sm2_key_pin, uint8_t *sm4_key_pin,
	uint8_t *ins_enc_in, uint32_t *ins_hash_in, ECCSignature *ins_sign_in, uint8_t *ins_data_out)
{
	uint32_t ret = 0;
	
	//dec------------
	ret = access_key(KEY_TYPE_SM4, sm4_key_id, sm4_key_pin);
	if(ret)
	{
        printf("[ERROR] Access SM4 key faild (Key ID: %d)\n", sm4_key_id);
	}
	//解密
	ret = sm4_init_inkey(1);
	if(ret)
	{
        printf("[ERROR] SM4 init faild in DEC mode! (Error code: 0x%04X)\n", ret);
	}
	ret = sm4_enc_dec(ins_enc_in, ins_data_out);
	if(ret)
	{
		//printf("SM4 enc faild!\n");
		return 0x160;
	}
	else
	{
        printf("[INFO] SM4 decryption completed successfully\n");
	}
	release_key(KEY_TYPE_SM4, sm4_key_id);
	
	//hash-------------------
	SM3_Handle_t s_handle;
	uint32_t ins_hash_temp[8] = {0};
	memset(&s_handle, 0x0, sizeof(SM3_Handle_t));
	uint32_t ins_data_out_u32_temp[4] = {0};
	memcpy(ins_data_out_u32_temp, ins_data_out, 16);
	ret = sm3_init(&s_handle);
	if(ret)
	{
        printf("[ERROR] SM3 init faild! (Error code: 0x%04X)\n", ret);
	}
	for(int i = 0; i < 4; i++)
	{
		ret = sm3_update(&s_handle, ins_data_out_u32_temp[i]);
		if(ret)
		{
            printf("[ERROR] SM3 update faild in round %d! (Error code: 0x%04X)\n", i, ret);
			break;
		}
	}
	ret = sm3_final(&s_handle, ins_hash_temp);
	if(ret)
	{
        printf("[ERROR] SM3 clear faild! (Error code: 0x%04X)\n", ret);
	}
	if(memcmp(ins_hash_in, ins_hash_temp, 32) != 0)
	{
		//printf("Hash result mismatch!\n");
		return 0x161;
	}
	else
	{
        printf("[INFO] Hash verification passed\n");
	}
	//veri---------------------
	ret = access_key(KEY_TYPE_SM2, sm2_key_id, sm4_key_pin);
	if(ret)
	{
        printf("[ERROR] Access SM2 key faild! (Key ID: %d)\n", sm2_key_id);
	}
	ret = sm2_verify_inkey(ins_sign_in, ins_hash_in);
	release_key(KEY_TYPE_SM2, sm2_key_id);
	if(ret)
	{
		//printf("SM2 veri faild!\n");
		return 0x162;
	}
	else
	{
        printf("[INFO] SM2 signature verification passed\n");
	}
	
	return 0;
}


void door_ctrl(uint8_t state)
{
	//关门
	if(state == 0)
	{
		setSegNum(1, SEG7_CHAR_L, 1, SEG7_CHAR_C);
	}
	//开门
	else
	{
		setSegNum(1, SEG7_CHAR_o, 1, SEG7_CHAR_P);
	}
}


void Button_IntrHandler(unsigned char button_state)
{
	if((button_state & 0b1000) == 0b1000){
		//printf("button4 int\n");
		//使能标志位
		ins_flag = 1;
		RegWrite(0xbf20f00c, 0x8);//clr
	}
}


void HWI0_IntrHandler(void)
{	
	unsigned int int_state;
	int_state = RegRead(0xbf20f014);

	if((int_state & 0x10) == 0x10){
		//Timer_IntrHandler();
	}
	else if(int_state & 0xf){
		Button_IntrHandler(int_state & 0xf);
	}
}


int main(int argc, char** argv)
{
    // 系统初始化
    printf("**********************************************************************\n");
    printf("*   INITIALIZING SECURE ACCESS CONTROL SYSTEM    *\n");
    printf("**********************************************************************\n");
	
	uint32_t ret = 0;
	
	printf("[INFO] System initialization started...\n");
    printf("-----------------------------------------------\n");
	ret = write_key(KEY_TYPE_SM2, 0, pin, &prikey, &pubkey, NULL);
	if(ret)
	{
        printf("[ERROR] SM2 key writing failed! (Error code: 0x%04X)\n", ret);
        printf("[WARN] Security alert: SM2 asymmetric key not initialized\n");
	}
	else
	{
		printf("[INFO] SM2 key pair securely stored\n");
	}
	ret = write_key(KEY_TYPE_SM4, 0, pin, NULL, NULL, sm4_key);
	if(ret)
	{
        printf("[ERROR] SM4 key writing failed! (Error code: 0x%04X)\n", ret);
        printf("[WARN] Security alert: SM4 symmetric key not initialized\n");
	}
	else
	{
        printf("[INFO] SM4 key securely stored\n");
	}
	exti_key_init(3, 1);
	door_ctrl(0);
	setLedBit(16, 1);
    printf("-----------------------------------------------\n");
    // 系统状态
    printf("[INFO] Security protection system activated\n");
    printf("-----------------------------------------------\n");
    printf("Hardware Information:\n");
    printf("  - Processor: LoongArch32R @ %d MHz\n", CORE_CLOCKS_PER_SEC/1000000);
    printf("  - System Clock: %d MHz\n", CONFREG_CLOCKS_PER_SEC/1000000);
    printf("-----------------------------------------------\n");
    printf("[INFO] Initial door state: DOOR LOCKED\n");
    printf("  Display: [ L ] [ C ] (Locked Closed)\n");
    printf("  LED Status: Security light(YELLOW) ON\n");
    printf("-----------------------------------------------\n");
    printf("[INFO] Waiting for access command (Press button 4 to trigger)...\n");
	
	while(1){
		if(ins_flag == 1)
		{
			printf("[INFO] Access control command received\n");
			switch_data = RegRead(0xbf20f400);//拨码开关
			ins_door[12] = switch_data & 0x1;
			printf("-----------------------------------------------\n");
			printf("Raw command data: \n");
			printf("  Header: 0x%02X  Footer: 0x%02X\n", ins_door[0], ins_door[15]);
			printf("  Command Type: %s (0x%02X)\n", 
				   ins_door[10]==0x11 ? "Door Control" : "Unknown", ins_door[10]);
			printf("  Parameter: 0x%04X\n", *(uint16_t*)&ins_door[11]);
			printf("-----------------------------------------------\n");
			printf("[INFO] Performing data encryption and signing...\n");
			ret = ins_enc_sign(0, 0, pin, pin, random_k, ins_door, ins_enc, ins_hash, &ins_sign);
			//入侵开关
			if(switch_data & 0x2)
			{
				//修改签名值
				ins_sign.r[1] = 0x0;
				ins_sign.s[2] = 0x0;
			}
			
			printf("[INFO] Starting command decryption and verification...\n");
			ret = ins_dec_veri(0, 0, pin, pin, ins_enc, ins_hash, &ins_sign, ins_dec);
			
			//正确的指令、哈希、签名
			if(!ret)
			{
				door_state = ins_dec[12];
				door_ctrl(ins_dec[12]);
				setLedBit(15, ins_dec[12]);
				setLedBit(1, 0);
				printf("[INFO] Verification PASSED - Command valid\n");
				printf("-----------------------------------------------\n");
				printf("Executing door state change: %s\n", ins_dec[12] ? "OPEN" : "CLOSE");
				printf("  Display: %s\n", 
					   ins_dec[12] ? "[ P ] [ o ] (Please open)" : "[ L ] [ C ] (Locked Closed)");
				printf("  LED Status: Door light(%s)\n", ins_dec[12] ? "ON" : "OFF");
				printf("-----------------------------------------------\n");
			}
			//被攻击
			else
			{
				printf("[ERROR] Verification FAILED - Security alert!\n");
				printf("-----------------------------------------------\n");
				printf("Error code: 0x%03X\n", ret);
				attack_count++;
				switch(ret)
				{
					case 0x260: printf("  Reason: SM4 encryption failure\n"); break;
					case 0x261: printf("  Reason: SM3 hash computation failure\n"); break;
					case 0x262: printf("  Reason: SM2 signing failure\n"); break;
					case 0x160: printf("  Reason: SM4 decryption failure\n"); break;
					case 0x161: printf("  Reason: Hash mismatch\n"); break;
					case 0x162: printf("  Reason: SM2 verification failure\n"); break;
					default:
						break;
				}
				printf("  Total attacks blocked: %d\n", attack_count);
				printf("  LED Status: Alarm light(YELLOW) ON\n");
				printf("-----------------------------------------------\n");
				setLedBit(1, 1);
			}
			printf("[INFO] System status summary\n");
			printf("+---------------------------------------------+\n");
			printf("| Current door state: %-8s\n", 
				   door_state ? "OPEN" : "CLOSED");
			printf("| Security level: %-10s\n", 
				   attack_count ? "ALERT" : "NORMAL");
			printf("| Security incidents: %-3d\n", attack_count);
			printf("+---------------------------------------------+\n");
			ins_flag = 0;
		}
		delay_ms(1);
	}
}
